home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / tools / ask / gmd / source / gmd.s < prev    next >
Text File  |  2000-02-16  |  55KB  |  2,014 lines

  1. *********************************************************************
  2. *    GMD:GetMojiDriver V2.0
  3. *        Copyright (C) 1996-98,2000 by AIG-Soft
  4. *********************************************************************
  5.  
  6.     .include    defines.mac
  7.     .include    fefunc.dis
  8.     .include    pspdef.mac
  9.     .include    gmd.mac
  10.     .lall        * マクロを展開して表示する(主にデバッグ用)
  11.  
  12. .ifndef    _FNTADR
  13. _FNTADR        equ    $16        * IOCS _FNTADR
  14. .endif
  15.  
  16. ZAREA        equ    1024        * ZAREA>=HAREAかつ4の倍数のこと
  17. HAREA        equ    256        * 
  18. ZMASK        equ    ZAREA-1        * bit mask
  19. HMASK        equ    HAREA-1        * bit mask
  20.  
  21. *********************************************************************
  22. *    常駐ルーチン
  23. *********************************************************************
  24.  
  25.     .text
  26.     .even
  27. DevHead:    * デバイスヘッダー
  28.     .dc.l    -1            * next device none
  29.     .dc.w    %11000000_00100000    * char device/IOCTRL ok/RAW
  30.     *        ??         ? 0000
  31.     .dc.l    Dev_start
  32.     .dc.l    Dev_main
  33. DevName    .dc.b    '@MOJI   '        * devive name
  34. *         12345678        * /Gで@GMDになる
  35. GMDsym    .dc.b    'AIG-GMD '        * GMD Symbol
  36.  
  37. *********************************************************************
  38. * ワーク1
  39. *********************************************************************
  40. * 固定値(この位置は変更しないこと;gmd.macで参照している)
  41.  
  42. API:    .dc.l    APImain        * APIアドレス
  43. Ver1:    .dc.b    2        * バージョン番号整数桁
  44. Ver2:    .dc.b    0        * バージョン番号小数桁:x1-x9(v1.01とか)は表せない
  45.     .even
  46.  
  47. *--------------------------------------------------------------------
  48. * 変化値
  49.  
  50. ProcAD:    .dc.l    0    * このプロセスの先頭アドレス(!=DevHead/常駐解除時に必要)
  51. Dev_A5:    .dc.l    0    * a5 save work
  52. *
  53. Zcodes    .dc.l    0    * ここはワークエリアそのものではなく
  54. Hcodes    .dc.l    0    *   そのアドレスを格納する
  55. * 以下の4つは必ず並べること(一気処理するから)
  56. Zsumx    .ds.b    ZAREA    * 各ハッシュ値になるキャラクター数
  57. Hsumx    .ds.b    HAREA    * Z~は全角,H~は半角
  58. Ztops    .ds.w    ZAREA    * codes内での各ハッシュ値毎の先頭位置
  59. Htops    .ds.w    HAREA    *
  60. *
  61. WriteAD    .dc.l    NonErr    * API_Read/ReadTangoの書き込みルーチンアドレス
  62. GroupAD    .dc.l    WDGroup    * API_ReadTangoのGroupルーチンアドレス
  63. badrs    .dc.l    -1    * 1回前の画面アドレス
  64. by    .dc.w    -1    * 1回前のy座標
  65. fdev    .dc.b    0    * device driver flag : 0:常駐プログラム , <>0:デバイスドライバー
  66. Fbmode    .dc.b    0    * ワークの位置 : =0:プログラム後部 , <>0:高位メモリー
  67. JLock    .dc.b    0    * 常駐解除ロックカウント : =0:解除可能 , >0:解除不可
  68. CurSw    .dc.b    0    * カーソル状態(=0:非表示,<>0:表示)
  69. RevMode    .dc.b    0    * 反転文字まで読むかどうか(=0:読まない,<>0:読む)
  70.     .even
  71.  
  72. *********************************************************************
  73. * APIルーチン
  74. *********************************************************************
  75.  
  76. APImain:
  77. * コマンドサーチ&実行
  78. * d0.b=コマンド(未定義コマンドは暴走する)
  79. * d0.l以外は保存
  80. * あらかじめスーパーバイザーモードにしてから呼び出すこと
  81. *(カーソルやフォントROMを直接いじるから)
  82.     * APImain内ではd0,d7,a0,a1以外破壊しない。
  83.     * d1-d6,a2-a6は引数として予約している。
  84.     movem.l    d1-d7/a0-a6,-(sp)
  85.     moveq.l    #0,d7            * for .b -> .l
  86.     move.b    d0,d7            * command d0.b = d7.l
  87.     add.w    d7,d7            * *2 (for word)
  88.     moveq.l    #0,d0            * for .b/.w -> .l
  89.     move.w    CtableN(pc,d7.w),d7
  90.     jsr    CtableN(pc,d7.w)    * 実行 -> d0.l
  91.     *
  92.     movem.l    (sp)+,d1-d7/a0-a6
  93.     rts
  94. *
  95.     * コマンドジャンプアドレス
  96. CtableN:    * 数値コマンド(0~番号順)
  97.     .dc.w    API_reserve-CtableN    * 未定義
  98.     .dc.w    API_Read1-CtableN    * <-d1.l ->d0.l
  99.     .dc.w    API_ReadTango-CtableN    * <-d1.l ->d0.l
  100.     .dc.w    API_Read-CtableN    * <-d1.l,d2.w ->d0.l
  101.     .dc.w    API_SetWriter-CtableN    * <-a2.l ->d0.l
  102.     .dc.w    API_SetGroup-CtableN    * <-a2.l ->d0.l
  103.     .dc.w    API_MoveCursor-CtableN    * <-d1.w
  104.     .dc.w    API_ReadVer-CtableN    * ->d0.w
  105.     .dc.w    API_JLock-CtableN    * ->d0.b
  106.     .dc.w    API_JUnlock-CtableN    * ->d0.b
  107.     .dc.w    API_DevNameA-CtableN    * <-a2.l
  108.     .dc.w    API_RevMode-CtableN    * <-d1.l
  109.     .even
  110.  
  111. *********************************************************************
  112. * 基本内部ルーチン1:内部状態設定/参照
  113. *********************************************************************
  114.  
  115. API_ReadVer:    * バージョン読みだし
  116.     move.w    Ver1(pc),d0        * d0.h.b=整数,d0.l.b=小数
  117. API_reserve:    * 未定義コマンド
  118.     rts
  119.  
  120. *--------------------------------------------------------------------
  121.  
  122. API_JLock:    * 常駐ロック
  123. * -> d0.b ロックカウント
  124. * 特にチェックはしていないが、.bの+領域0~128段のみ可能
  125.     move.b    JLock(pc),d0
  126.     addq.b    #1,d0
  127.     move.b    d0,JLock
  128.     rts
  129. *
  130. API_JUnlock:    * 常駐アンロック
  131.     move.b    JLock(pc),d0
  132.     subq.b    #1,d0
  133.     bmi    @f        * マイナスにはしない
  134.     move.b    d0,JLock
  135. @@:    rts
  136.  
  137. *--------------------------------------------------------------------
  138.  
  139. API_RevMode:    * 反転文字読み取りモード
  140.     tst.l    d1
  141.     bmi    @f        * -1:現在モード読み取り
  142.     sne    RevMode        * d1=0->0,<>0->$ffに限定
  143. @@:    moveq.l    #0,d0        * for .b=.l
  144.     move.b    RevMode(pc),d0
  145.     rts
  146.  
  147. *********************************************************************
  148. * 基本内部ルーチン2:文字読みとりメイン
  149. *********************************************************************
  150. * 以下の基本ルーチンは必ずスーパーバイザーモードで動かすこと
  151. *********************************************************************
  152. * IOCS _FNTADRの代わり
  153. * ちょっとでも早くなるようにIOCSを直接呼び出す
  154. FNTADR:
  155.     moveq.l    #8,d2        * フォントサイズ固定(8/16*16)
  156. FNTJMP:    jmp    0.l        * d0,d1,d2破壊
  157. AFNTADR    equ    FNTJMP+2    * IOCS _FNTADRのアドレス(直接飛ぶため)
  158.  
  159. *--------------------------------------------------------------------
  160.  
  161. LSum:
  162. * 全角文字フォントハッシュ計算
  163. * a1 <- font adrs (fb[2*16])
  164. * a2は破壊しないこと
  165. * -> d0.l.w : ハッシュ値(マスクはせず), NOCHR=空白文字である(s160不定)
  166. *    d0.h.w : 第2指標(s160)
  167.     move.l    d7,-(sp)
  168.     *
  169.     lea    2(a1),a0    * p=&fb[2]
  170.     moveq.l    #0,d2        * s16=0
  171.     moveq.l    #0,d7        * s160=0
  172.     moveq.l    #11-1,d0    * 11lines = 1~11
  173. @@:    moveq.l    #0,d1        * for .b -> .w
  174.     move.b    (a0),d1        * *p.b (左半分のみ)
  175.     add.w    d1,d2        * s16+=*p
  176.     move.w    (a0)+,d1    * eor.w    (a0),d7が出来ないので
  177.     eor.w    d1,d7        * 半角処理時に左右分けされるのでビット演算以外使えない
  178.     dbra    d0,@b
  179.     *
  180.     tst.w    d2        * s16=0?
  181.     bne    1f        * No
  182.     * 空白の可能性有り
  183.     moveq.l    #16/2-1,d0    * 16lines = 0~15
  184. @@:    tst.l    (a1)+        * *p.w*2=0?(2ライン分一気チェック)
  185.     bne    1f        * No = 空白ではない
  186.     dbra    d0,@b
  187.     moveq.l    #-1,d2        * 空白の印:move.w #NOCHR,d0だけど、高速化のため
  188.     *
  189. 1:    move.w    d7,d0        * s160.h.w / 半角の時はs160は上位8ビットのみ使うこと(&$ff00)
  190.     swap    d0
  191.     move.w    d2,d0        * s16.l.w
  192.     *
  193.     move.l    (sp)+,d7
  194.     rts
  195.  
  196. *--------------------------------------------------------------------
  197.  
  198. FontCmp    macro    mask,tops,codes,sumx,cnt,HIKAKU,haba
  199. * ハッシュ表からコードを読み取ってフォント比較
  200. Local    L1,L2,L3,L4
  201. * d5.l.w <- s16
  202. * d5.h.w <- s160
  203.     .if    haba==1        * 半角の時
  204.     move.w    #$ff00,d0    * s160の下位8ビットを無効にする(半角は幅8ドットなので)
  205.     swap    d0
  206.     move.w    #mask,d0
  207.     and.l    d5,d0
  208.     move.l    d0,d4        * d4.h.w=s160
  209.     .else
  210.     move.l    d5,d4        * d4.h.w=s160
  211.     move.w    d5,d0        * s16
  212.     and.w    #mask,d0    * s16&mask
  213.     .endif
  214.     *
  215.     lea    sumx(pc),a0
  216.     clr.w    d4        * for .b -> .w (h.wは使用中なのでmoveq.lはだめ)
  217.     move.b    (a0,d0.w),d4    * sumx[s16]
  218.     subq.w    #1,d4        * -1 for dbra
  219.     *
  220.     add.w    d0,d0        * tops[s16] ; topsは.wだから
  221.     move.l    codes(pc),a2
  222.     lea    tops(pc),a0
  223.     add.w    (a0,d0.w),a2    * p=&codes[tops[s16]] (codesは32768より小さいので.wで届く)
  224.     *
  225. L1:    swap    d4        * d4.h.w=ループカウント <-> .l.w=s160
  226.     cmp.w    (a2)+,d4    * s160==*p++(s160)?
  227.     beq    L4        * -> Yes
  228.     * s160が不一致:フォントは絶対一致しない
  229.     addq.w    #2,a2        * cを飛ばす
  230.     bra    L2        * 次の文字へ
  231.     *
  232. L4:    move.w    (a2)+,d3    * c=*p++
  233.     move.w    d3,d1        * c
  234.     bsr    FNTADR        * d0,d1,d2破壊
  235.     move.l    d0,a1        * ->Font adrs(from ROM)
  236.     lea    fb(pc),a0    * fb(from TEXT)
  237.     *
  238.     moveq.l    #cnt-1,d1    * cnt lines (-1 for dbra)
  239. L3:    HIKAKU            * フォント比較ルーチン
  240.     bne    L2        * 不一致
  241.     dbra    d1,L3
  242.     * 一致
  243.     moveq.l    #haba,d0    * d0.l=$000幅_code : 幅
  244.     swap    d0
  245.     move.w    d3,d0
  246.     bra    RCret        * return(c) ; (マクロ外部のラベル)
  247.     *
  248. L2:    * 不一致
  249.     swap    d4        * d4.l.w=ループカウンタ
  250.     dbra    d4,L1
  251.     endm
  252.  
  253. Zhikaku    macro
  254. * 全角フォント比較
  255.     cmp.l    (a1)+,(a0)+
  256.     endm
  257.  
  258. Hhikaku    macro
  259. * 半角フォント比較
  260.     cmp.b    (a1)+,(a0)+
  261.     addq.w    #1,a0        * 画面フォントは+2ずつ、ROMフォントは+1ずつ
  262.                 * a?のaddはフラグが変わらない
  263.     endm
  264.  
  265. *---------------------------
  266.  
  267. ReadChar:
  268. * 1文字読みとり
  269. * d0.h.w=tx , d0.l.w=ty
  270. * -> d0.l.w : 文字 (NOCHR=該当文字がない)
  271. *    d0.h.w : 文字幅-1 : 0=半角(1/2,1/4角文字を含む) , 1=全角
  272. * d0以外破壊しない
  273.     movem.l    d1-d7/a0-a2,-(sp)
  274.     *
  275.     * 読みとりテキストアドレス算出
  276.     * d0.h.w=tx , d0.l.w=ty
  277.     * x座標は連続する場合が多いので、前回の値を覚えて再計算を省き高速化する
  278.     cmp.w    by,d0        * 前回とy座標が同じ?
  279.     bne    @f
  280.     * 前回とy座標が同じ=x座標分だけ再計算(高速化のため)
  281.     move.l    badrs,a1
  282.     swap    d0        * d0.h.w=ty , d0.l.w=tx
  283.     add.w    d0,a1        * x座標のみ更新
  284.     bra    10f
  285.     *
  286. @@:    * 新規アドレス計算
  287.     move.w    d0,by        * 今回のy座標を記録
  288.     move.l    #TPLANE0,a1    * TPLANE0
  289.     add.l    MTXOFST.w,a1    * +*TXOFST(ショートアドレッシング)
  290.     swap    d0        * d0.h.w=ty , d0.l.w=tx
  291.     move.w    d0,d6        * tx保存
  292.     clr.w    d0        * = and.l #$ffff0000,d0    * ty(.h)のみ
  293.     lsr.l    #5,d0        * ty>>5 = ty<<11 = ty*2048(16*TLSIZE:128)
  294.     add.l    d0,a1
  295.     move.l    a1,badrs    * 今回のアドレスを記録(x=0のアドレス)
  296.     add.w    d6,a1        * +tx
  297. 10:    move.l    a1,a2
  298.     add.l    #TPSIZE,a2    * TPLANE1
  299.     *
  300.     moveq.l    #0,d6        * 反転処理中でないの印
  301.     * 文字フォント読みとり(常に16dot=2byte*16line)
  302.     lea    fb(pc),a0    * fb(読みとりバッファー)
  303.     moveq.l    #0,d7        * bit0&左半分全0判定用
  304.     moveq.l    #16-1,d1    * 16lines
  305.     * 高速化のため座標別に読みとりを変える
  306.     * 68030機種では偶数座標処理だけでいける
  307.     move.l    a1,d0
  308.     btst.l    #0,d0        * アドレス判定(奇数/偶数)
  309.     beq    xeven        * -> 偶数アドレス
  310.     * 奇数アドレス : byte単位
  311. @@:    move.b    (a2)+,d0    *  TPLANE1
  312.     or.b    (a1)+,d0    * |TPLANE0
  313.     move.b    d0,(a0)+
  314.     or.b    d0,d7        * bit0判定用(左側)
  315.     move.b    (a2),d0
  316.     or.b    (a1),d0
  317.     move.b    d0,(a0)+
  318.     lea    127(a1),a1    * next line
  319.     lea    127(a2),a2    * next line
  320.     dbra    d1,@b
  321.     bra.s    FontChk
  322.     *
  323.     * 偶数アドレス : word単位
  324. xeven:    move.w    (a2),d0        *  TPLANE1
  325.     or.w    (a1),d0        * |TPLANE0
  326.     move.w    d0,(a0)+
  327.     or.w    d0,d7        * bit0判定用
  328.     lea    128(a1),a1    * next line
  329.     lea    128(a2),a2    * next line
  330.     dbra    d1,xeven
  331.     move.w    d7,-(sp)
  332.     move.b    (sp)+,d7    * d0.l.h.b -> d0.l.l.b ; 左側
  333.     *
  334. FontChk:
  335.     * フォント-文字判定
  336.     lea    fb(pc),a1    * fb (TEXT)
  337.     bsr    LSum        * 全角用ハッシュ計算(s16/s160)
  338.     cmp.w    #NOCHR,d0    * s16=NOCHR? : 全角分空白?
  339.     beq     RCspc        * Yes -> return(半角SPCにする)
  340.     * 空白ではない
  341.     move.l    d0,d5        * s16(l.w)/s160(h.w)
  342.     *
  343.     * 全角・半角どちららしい?
  344.     tst.b    d7
  345.     beq    @f        * 全ライン全ビット0=なら空白だが、左半分が空白の全角文字
  346.                 * があるので、この時は常に全角文字優先にする。
  347.     btst.l    #0,d7        * bit0=1:ne;全角 , 0:eq;半角
  348.     beq    Hankaku
  349.     *
  350. @@:    moveq.l    #1,d7        * 全角優先の印にする
  351. Zenkaku:    * 全角フォント比較
  352.     FontCmp    ZMASK,Ztops,Zcodes,Zsumx,2*16/4,Zhikaku,2    * 一致ならRCretへ
  353.     * 全角では一致するフォントがない
  354.     btst.l    #0,d7        * bit0=1:ne;全角 , 0:eq;半角
  355.     beq    RCnret        * 半角優先時に全角が終わったら終了
  356.     *
  357. Hankaku:    * 半角比較
  358.     * 半角スペースではないか?
  359.     tst.b    d7        * 左側全ライン全ビットor値=0ならスペース
  360.     beq    RCspc        * スペースである
  361.     * スペースではない
  362.     FontCmp    HMASK,Htops,Hcodes,Hsumx,16,Hhikaku,1        * 一致ならRCretへ
  363.     * 半角では一致するフォントがない
  364.     btst.l    #0,d7        * bit0=1:ne;全角 , 0:eq;半角
  365.     beq    Zenkaku        * 半角優先時なら全角へ
  366.     *
  367. RCnret:    * 一致するフォント全く無し
  368.     tst.b    RevMode        * 反転文字も読み取る?
  369.     beq    @f        * いいえ
  370.     * 読み取る
  371.     tst.b    d6        * もうすでに反転文字処理した?
  372.     bne    @f        * Yes
  373.     * 反転文字処理へ
  374.     st    d6        * 反転処理中の印
  375.     * フォント反転
  376.     lea    fb(pc),a1    * fb (TEXT)
  377.     moveq.l    #16/2-1,d0    * 2ラインまとめて処理
  378. 1:    not.l    (a1)+        * 全ビット反転
  379.     dbra    d0,1b
  380.     bra    FontChk        * 元に戻ってもう一度処理へ
  381.     *
  382. @@:    * 半角スペース相当で扱う時ため幅1にしておく
  383.     move.l    #$0001_0000|NOCHR,d0    * $0001ffff (moveqにしないこと)
  384. RCret:    movem.l (sp)+,d1-d7/a0-a2
  385.     rts
  386.  
  387. RCspc:    * 半角スペース
  388.     move.l    #$0001_0020,d0
  389.     bra.s    RCret
  390.  
  391. *--------------------------------------------------------------------
  392.  
  393. SetCur:
  394. * d1.l <- x,y : (-1,-1)なら現在のカーソル座標
  395. * -> d7.l -1:カーソル移動する , <>-1:戻すカーソル座標
  396.     move.l    CSRX.w,d7    * 現在カーソル位置保存(カーソル移動しないの印)
  397.     * 画面を越える座標の時は現在カーソル位置とする
  398.     * (-1,-1)も越える
  399.     * 1024dot*1024line=128桁*64行まで対応
  400.     cmp.l    #128.shl.16+64,d1
  401.     bcs    CUROFF        * No (0~,0~)
  402.     * 現在カーソル位置:カーソルは移動
  403.     move.l    d7,d1
  404.     moveq.l    #-1,d7        * カーソル移動するの印
  405. CUROFF:    * d1.l <- x,y
  406.     move.l    d0,-(sp)
  407.     move.b    CSRSWITCH.w,CurSw    * 現在の状態を保存
  408.     IOCS    _B_CUROFF    * カーソルoff
  409.     move.l    (sp)+,d0
  410.     rts
  411.  
  412. ResetCur:
  413. * d1.l <- x,y
  414. * d7.l <- -1:カーソル移動する , <>-1:戻すカーソル座標
  415.     tst.l    d7        * カーソル移動する?
  416.     bpl    CURON        * No (0~,0~)
  417.     move.l    d1,CSRX.w    * カーソルを移動
  418. CURON:
  419.     tst.b    CurSw        * 元がonならonする
  420.     beq    @f
  421.     move.l    d0,-(sp)
  422.     IOCS    _B_CURON    * カーソルon
  423.     move.l    (sp)+,d0
  424. @@:    rts
  425.  
  426. *--------------------------------------------------------------------
  427.  
  428. API_Read1:
  429. * 指定座標から1文字読みとり
  430. * long GMDRead1(xy)
  431. * <- d1.h.w=x , d1.l.w=y ((-1,-1)で現在のカーソル位置、カーソルは常に動かない)
  432. * -> d0.l.w : 読みとった文字のコード (NOCHR=読み取れない)
  433. *    d0.h.w : 読みとった文字の幅
  434.     move.l    CSRX.w,d0    * 現在のカーソル座標
  435.     cmp.l    #128.shl.16+64,d1
  436.     bcc    @f        * >= -> (-1,-1):現在カーソル位置
  437.     move.l    d1,d0        * 指定座標
  438. @@:    bsr    CUROFF        * カーソルoff
  439.     bsr    ReadChar
  440.     bsr    CURON        * カーソルon
  441.     rts
  442.  
  443. *--------------------------------------------------------------------
  444.  
  445. API_SetWriter:
  446. * ReadTango/Readの書き込みルーチン設定
  447. * void GMDSetWriter(int (*func)())
  448. * Read/ReadTangoの書き込みルーチンを設定する
  449. * <- a2 : 書き込みルーチンアドレス
  450. *     書き込みチェックなどはそのルーチン内で行う
  451. *     引数は4(sp)で受ける , h.w=文字幅(1/2) , l.w=文字コード
  452. *     d0-d2/a0-a2以外保存すること , -> d0.l : 0=ok,<0=error
  453.     cmp.l    #0,a2
  454.     bne    @f
  455.     lea    NonErr(pc),a2    * a2=0のときはデフォルトにする
  456. @@:    move.l    WriteAD(pc),d0    * 元のアドレスを返す
  457.     move.l    a2,WriteAD
  458.     rts
  459.  
  460. *--------------------------------------------------------------------
  461.  
  462. API_SetGroup:
  463. * ReadTangoの文字コードグループ設定
  464. * void GMDSetGroup(int (*func)())
  465. * ReadTangoのGroupルーチンを設定する
  466. * <- a2 : Groupルーチンアドレス
  467. *     引数は4(sp)で受ける , h.w=文字幅(1/2) , l.w=文字コード
  468. *     d0-d2/a0-a2以外保存すること , -> d0.l : 0=ok,<0=error
  469.     cmp.l    #0,a2        * a2=0のときは標準Groupに設定する
  470.     bne    @f        * それ以外はユーザー設定
  471.     lea    WDGroup(pc),a2
  472. @@:    move.l    GroupAD(pc),d0    * 元のアドレスを返す
  473.     move.l    a2,GroupAD
  474.     rts
  475.  
  476. *--------------------------------------------------------------------
  477.  
  478. API_ReadTango:
  479. * 指定座標からの単語単位読みとり
  480. * long GMDReadTango(xy)
  481. * d1.l <-> x,y : (-1,-1)なら現在カーソル位置からカーソル移動付き
  482. * -> d0.l : 読みとった文字数 : バイトではなく半角/全角文字共に1と数える。
  483.     bsr    SetCur        * カーソル設定&off : x,y -> d1.l
  484.     move.l    WriteAD(pc),a3    * 書き込みルーチンアドレス
  485.     move.l    GroupAD(pc),a4    * Groupルーチンアドレス
  486.     moveq.l    #-1,d4        * 読みとった文字数(後で+1するため)
  487.     moveq.l    #-1,d6        * 最初のgroup
  488. @@:    bsr    ReadTANGO1    * -> d0.w(group)
  489.     addq.l    #1,d4        * 文字数+1
  490.     move.w    d0,d6
  491.     bpl    @b        * group>=0
  492.     * d1.l <- x,y
  493.     tst.l    d4        * 文字を読み取っている?
  494.     bne    @f        * 確実に
  495.     cmp.w    #NOCHR,d3    * いきなり読み取れなかった?
  496.     bne    @f        * no
  497.     * まったく読み取れていない
  498.     * カーソルをx+1する
  499.     moveq.l    #1,d3
  500.     bsr    MoveCur        * カーソル移動
  501. @@:    bsr    ResetCur    * カーソル設定&on
  502.     move.l    d4,d0        * 読みとった文字数
  503.     rts
  504.  
  505. *--------------------------------------------------------------------
  506.  
  507. ReadTANGO1:
  508. * 指定座標からの1文字読みとり(単語単位読みとり準備付き)
  509. * d1.l <-> x,y
  510. * d6.w <-  前のグループ(最初は<0)
  511. * a3   <-  書き込みルーチン
  512. * a4   <-  Groupルーチン
  513. * -> d3.w :  読み込んだ文字
  514. * -> d0.w : >=0:今度のグループ , -1:中断 , -2:書き込みエラー
  515.     movem.l    d4-d6,-(sp)
  516.     * d1.l=x,y
  517.     bsr    ReadSub        * -> d0.l.w=文字 , d0.h.w=文字幅 (d3も同じ)
  518.     beq    4f        * Yes
  519.     * 読み取れている
  520.     move.l    d3,-(sp)    * 4+2(sp)で受けること
  521.     jsr    (a4)        * Groupルーチン : -> d0.w
  522.     addq.w    #4,sp
  523.     cmp.w    d0,d6        * 前のグループと同じ?
  524.     beq    3f        * Yes
  525.     * 違うときはここまで(中断)
  526.     tst.w    d6        * 前のグループ<0?
  527.     bmi    3f        * Yes : 前との比較はしない
  528.     * 前のグループと違うときはここまで
  529.     move.l    d4,d1        * 座標復帰
  530. 4:    moveq.l    #-1,d0        * 中断
  531.     bra.s    @f
  532. *
  533. 3:    * 前と同じグループなので書き込む
  534.     move.w    d0,d5        * グループ退避
  535.     bsr    WriteSub    * 書き込み&カーソル移動
  536.     bne    @f        * エラーが発生している
  537.     move.w    d5,d0        * グループ復帰>0
  538. @@:    movem.l    (sp)+,d4-d6
  539.     rts
  540.  
  541. *--------------------------------------------------------------------
  542.  
  543. ReadSub:
  544. * 1文字読み込み
  545.     move.l    d1,d4        * 座標保存
  546.     move.l    d1,d0        * d0.l=x,y
  547.     bsr    ReadChar    * -> d0.l.w=文字 , d0.h.w=文字幅
  548.     move.l    d0,d3        * 保存
  549.     cmp.w    #NOCHR,d0    * 読み取れていない?
  550.     rts
  551.  
  552. WriteSub:
  553. * 文字書き込み&カーソル移動
  554. * d3.l <- h.w=文字幅(1/2) , l.w=文字
  555. * d4.l <- カーソル座標
  556. * a3   <- 書き込みルーチン
  557. * -> d3.w = 文字
  558. * -> d0.l : =0:ok , <>0:error
  559.     move.l    d3,-(sp)
  560.     jsr    (a3)        * 書き込みルーチン
  561.     addq.w    #4,sp
  562.     move.l    d4,d1        * 座標復帰
  563.     tst.l    d0        * 書き込めた?
  564.     bne    @f        * No
  565.     * カーソル移動(d0.l=0)
  566.     swap    d3        * d3.w=文字幅
  567.     bsr    MoveCur        * -> d1.l=x,y (d3.h.w破壊)
  568.     swap    d3        * d3.w=文字
  569.     tst.l    d0        * z=1
  570.     rts
  571. *
  572. @@:    * エラー
  573.     moveq.l    #-2,d0        * WTERR(z=0)
  574.     rts
  575.  
  576. *--------------------------------------------------------------------
  577.  
  578. API_MoveCursor:
  579. * 文字幅に合わせた現在カーソル移動
  580. * d1.w <- 移動幅(1/2)
  581.     bsr    CUROFF        * カーソルoff
  582.     move.w    d1,d3        * 移動幅
  583.     move.l    CSRX.w,d1    * 現在カーソル
  584.     bsr    MoveCur        * 移動処理
  585.     move.l    d1,CSRX.w    * カーソル移動
  586.     bsr    CURON        * カーソルon
  587.     rts
  588. *
  589. MoveCur:
  590. * カーソル移動
  591. * d1.l <- x|y -> d1.l
  592. * d3.w <- 移動幅(1/2)
  593. * (d1),d3破壊
  594. *(現在カーソルを移動させる時はカーソルをoffしてから行う必要がある)
  595.     swap    d1        * y|x
  596.     add.w    d3,d1        * x+=幅
  597.     cmp.w    CSRXMAX.w,d1    * x>WX? (WXまではok)
  598.     bhi    2f        * Yes
  599.     * x<=WX
  600.     swap    d1        * x|y
  601.     bra.s    1f
  602. *
  603. 2:    * x>WX -> x=0~
  604.     subq.w    #1,d3        * d3-1が新しい座標になる : d3=1->x=0 ...
  605.     move.w    d3,d1
  606.     swap    d1        * x|y
  607.     addq.w    #1,d1        * y++
  608.     cmp.w    CSRYMAX.w,d1    * y>WY?
  609.     bls    1f        * no(y<=WY)
  610.     clr.w    d1        * y=0
  611. 1:
  612.     rts
  613.  
  614. *--------------------------------------------------------------------
  615.  
  616. * 単語として読みとる区切り文字
  617. HanGP:    .dc.b    ' ,;:()。、・',$22,$27,0    * 1byte
  618. ZenGP:    .dc.b    '。、,',0,0        * 2byte(.wで読まれるので、EOTも0,0必要)
  619.     * よく出てくる順に置くこと
  620.     .even
  621.  
  622. WDGroup:
  623. * 単語単位グルーピング(標準)
  624. * 4(sp) <- h.w=文字幅(1/2) , l.w=code
  625. * -> d0.w : グループ番号 (h.wは不定でいい)
  626.     moveq.l    #1,d0        * 通常はグループ1
  627.     move.w    4+2(sp),d2    * 文字コード
  628.     cmp.w    #$ff,d2        * code>=$ff?
  629.     bcc    1f        * Yes -> 2バイト文字
  630.     moveq.l    #0,d1        * for .b -> .w
  631.     * 1byte文字チェック
  632.     lea    HanGP(pc),a0
  633. @@:    move.b    (a0)+,d1
  634.     beq    @f        * end of table
  635.     cmp.w    d1,d2        * 一致?
  636.     bne    @b        * no
  637.     * 一致したものはグループ2
  638.     moveq.l    #2,d0
  639. @@:    rts
  640.  
  641. 1:    * 2byte文字チェック
  642.     lea    ZenGP(pc),a0
  643. @@:    move.w    (a0)+,d1
  644.     beq    @f        * end of table
  645.     cmp.w    d1,d2        * 一致?
  646.     bne    @b        * no
  647.     * 一致したものはグループ2
  648.     moveq.l    #2,d0
  649. @@:    rts
  650.  
  651. *--------------------------------------------------------------------
  652.  
  653. API_Read:
  654. * 指定座標からの指定文字数分読みとり
  655. * long GMDRead(xy,size)
  656. * d1.l <-> x,y : (-1,-1)なら現在カーソル位置からカーソル移動付き
  657. * d2.w <-  size >0: 指定文字数(読み取れない文字があったら中止)
  658. *        <0:-指定文字数(読み取れない文字があっても半角スペースとして継続)
  659. *        =0:単語読み取り
  660. * 画面上文字数は最大で128*64=8192なのでword単位で十分
  661. * -> d0.l : 読みとった文字数 : バイトではなく半角/全角文字共に1と数える。
  662.     * 書き込みルーチンアドレス設定
  663.     moveq.l    #0,d5        * 読み取れない文字=中止の印
  664.     tst.w    d2        * size
  665.     beq    API_ReadTango    * size=0 : 単語読み取り
  666.     bpl    @f        * >0:指定文字数読み取り(読み取れない->中断)
  667.     * <0
  668.     sub.w    d2,d5        * d5=d5-d2 = d5=0-d2 -> -d2>0
  669.     move.w    d5,d2
  670.     moveq.l    #1,d5        * 読み取れない文字=スペースで継続の印
  671. @@:    bsr    SetCur        * カーソル設定&off : x,y -> d1.l
  672.     move.l    WriteAD(pc),a3    * 書き込みルーチンアドレス
  673.     moveq.l    #-1,d4        * 読みとった文字数(後で+1するため)
  674.     subq.w    #1,d2        * -1 or dbra
  675. @@:    bsr    ReadSize1    * -> d0.w(文字)
  676.     addq.l    #1,d4        * 文字数+1
  677.     cmp.w    #WTERR,d0
  678.     bhi    @f        * 中断
  679.     dbeq    d2,@b        * 書き込みエラーでない
  680.     beq    @f        * エラーの時
  681.     addq.l    #1,d4        * 最後まで読めた時は文字数+1
  682.     * d1.l <- x,y
  683. @@:    bsr    ResetCur    * カーソル設定&on
  684.     move.l    d4,d0        * 読みとった文字数
  685.     rts
  686.  
  687. *--------------------------------------------------------------------
  688.  
  689. ReadSize1:
  690. * 指定座標からの1文字読みとり(連続読み込み準備付き)
  691. * d1.l <-> x,y
  692. * d5.w <-  =0:読み取れなかったら中断 , <>0:読み取れない文字は半角スペース
  693. * a3   <-  書き込みルーチン
  694. * d0.w ->  読み込んだ文字>0 , NOCHR:読み取れない , WTERR:書き込みエラー
  695.     movem.l    d2-d4,-(sp)
  696.     * d1.l=x,y
  697.     bsr    ReadSub        * -> d0.l.w=文字 , d0.h.w=文字幅
  698.     bne    1f        * no
  699.     * 読み取れていない
  700.     tst.w    d5        * 中断?
  701.     beq    @f        * Yes
  702.     move.l    #$0001_0020,d3    * 半角スペース(幅=1)
  703. 1:    * 書き込む
  704.     bsr    WriteSub    * 書き込み&カーソル移動
  705.     bne    @f        * エラーが発生している
  706.     move.l    d3,d0        * d0.w=文字
  707. @@:    movem.l    (sp)+,d2-d4
  708.     rts
  709.  
  710. *********************************************************************
  711. * 基本内部ルーチン5:デバイス名取得
  712. *********************************************************************
  713.  
  714. API_DevNameA:
  715. * a2 <- デバイス名格納エリア
  716.     lea    DevName(pc),a0
  717.     moveq.l    #8-1,d1        * -1 dbra
  718. @@:    move.b    (a0)+,d0
  719.     cmp.b    #' ',d0        * ' 'の直前まで
  720.     beq    2f
  721.     move.b    d0,(a2)+
  722.     dbra    d1,@b        * または8バイトまで
  723. 2:    clr.b    (a2)        * EOS
  724.     rts
  725.  
  726. *********************************************************************
  727. * デバイスドライバー:コマンド解析&初期処理
  728. *   デバイスドライバーは(たぶん)常にスーパーバイザーモードで走る。
  729. *********************************************************************
  730.  
  731. Dev_start:
  732.     move.l    a5,Dev_A5        * save リクエストヘッダーアドレス
  733.     rts
  734.  
  735. *********************************************************************
  736.  
  737. Dev_main:
  738.     movem.l    d1-d7/a0-a6,-(sp)    * push register
  739.     move.l    Dev_A5(pc),a5        * a5 <- リクエストヘッダーアドレス
  740.     *
  741.     moveq.l    #0,d0            * for .b -> .l
  742.     move.b    2(a5),d0        * d0.l <- コマンド番号
  743.     add.w    d0,d0            * *2
  744.     move.w    comtable(pc,d0.w),d0    * read call offset address
  745.     jsr    comtable(pc,d0.w)    * call subroutines
  746.     *
  747.     move.l    d0,d1
  748.     move.b    d1,3(a5)        * set error code (low)
  749.     lsr.w    #8,d1            * high -> low (8bit)
  750.     move.b    d1,4(a5)        * set error code (high)
  751.     movem.l    (sp)+,d1-d7/a0-a6    * pop register
  752.     rts
  753.  
  754. *********************************************************************
  755.  
  756.     .even
  757. comtable:    * コマンドアドレス(相対アドレス表)
  758.     .dc.w    Dev_init-comtable    * 初期化
  759.     .dc.w    COM_ERR-comtable
  760.     .dc.w    COM_ERR-comtable
  761.     .dc.w    NonErr-comtable        * ioctrl in
  762.     .dc.w    NonErr-comtable        * 入力
  763.     .dc.w    NonErr-comtable        * 先行入力
  764.     .dc.w    NonErr-comtable        * 入力バッファーチェック
  765.     .dc.w    NonErr-comtable        * バッファークリア
  766.     .dc.w    Dev_Write-comtable    * 出力(verify off)
  767.     .dc.w    Dev_Write-comtable    * 出力(verify on)
  768.     .dc.w    NonErr-comtable        * 出力ステータスチェック
  769.     .dc.w    COM_ERR-comtable
  770.     .dc.w    NonErr-comtable        * ioctrl out
  771.     .even
  772.  
  773. *********************************************************************
  774. * エラーコマンド
  775.  
  776. COM_ERR:
  777.     move.w    #$5003,d0    * $50 = 中止&無視 , $03 = コマンドコードが不正
  778.     rts
  779.  
  780. *********************************************************************
  781.  
  782. Dev_Write:            * 出力(verify on/off)
  783. * "x,y,size,fname" / "x.y.size.fname"
  784. * ファイルがオープンできないときは単に動作しないだけ
  785. * エラーは読みとりサイズ=-1を返す
  786.     move.l    14(a5),a2    * buffer
  787.     move.l    18(a5),d3    * size
  788.     bsr    DevWriteSub
  789.     move.l    d0,18(a5)    * <0:エラー , >=0:読みとった文字数
  790.     * ただし、デバイスとしてのエラーは出さない
  791. NonErr:    moveq.l    #0,d0        * no error
  792.     rts
  793.  
  794. *--------------------------------------------------------------------
  795.  
  796. Atoi:
  797. * 10進文字列読み取り(負号,',','.'対応)
  798. * a2 <-> str
  799. * -> d0.w : 数値($0000-$ffff) , $ffffffff=エラー
  800.     move.l    d1,-(sp)
  801.     moveq.l    #1,d1        * 負号無し
  802.     cmp.b    #'-',(a2)
  803.     bne    @f
  804.     * '-'がある
  805.     moveq.l    #0,d1        * 負号あり
  806.     addq.w    #1,a2
  807.     subq.l    #1,d3
  808.     beq    Aerr1        * 負号しかない
  809. @@:    swap    d1        * for .b -> .w (.h.w=0/1)
  810.     moveq.l    #0,d0        * num=0
  811. @@:    move.b    (a2)+,d1
  812.     beq    Aret        * EOS
  813.     cmp.b    #'0',d1
  814.     bmi    Aerr        * '0'より小さい -> 数字文字でない
  815.     cmp.b    #'9',d1
  816.     bhi    Aerr1        * Yes -> 数字文字でない
  817.     * '0'~'9'
  818.     sub.b    #'0',d1
  819.     add.w    d0,d0        * *2
  820.     add.w    d0,d1
  821.     add.w    d0,d0        * *4
  822.     add.w    d0,d0        * *8
  823.     add.w    d1,d0        * *8+(*2+c) = *10+c
  824.     subq.l    #1,d3
  825.     bne    @b        * 文字列終わりまで
  826. Aret:    swap    d1
  827.     tst.w    d1        * 負号あり?
  828.     bne    @f        * No
  829.     sub.w    d0,d1        * 0-d0
  830.     move.w    d1,d0        * d0.w
  831. @@:    move.l    (sp)+,d1
  832.     rts
  833.  
  834. Aerr:    * 途中でbase進文字でない文字が出て来た
  835.     cmp.b    #',',d1        * ,
  836.     beq    Aret        * Yes
  837.     cmp.b    #'.',d1        * .
  838.     beq    Aret        * Yes
  839. * ここでは数字の後にファイル名があるため、数字のみで終わることはない。
  840. * 従って、そういう時はエラーにする。
  841. *    cmp.b    #' ',d1        * コントロールコード($1a,$0d,$0a等)は文字列終了とみなす
  842. *    bmi    Aret
  843. Aerr1:    * エラー
  844.     moveq.l    #-1,d0
  845.     move.l    (sp)+,d1
  846.     rts
  847.  
  848. *--------------------------------------------------------------------
  849.  
  850. DevWriteSub:
  851. * a2.l <- 文字列(EOSでは終わっていない)
  852. * d1.l <- 文字列長
  853.     * 座標読みだし -> d1.l
  854.     bsr    Atoi            * x -> d0.w
  855.     tst.l    d0
  856.     bmi    1f            * 数字エラー
  857.     move.w    d0,d1
  858.     swap    d1
  859.     bsr    Atoi            * y -> d0.w
  860.     tst.l    d0
  861.     bmi    1f            * 数字エラー
  862.     move.w    d0,d1            * d1=x|y
  863.     * サイズ読みだし -> d2.w
  864.     bsr    Atoi
  865.     tst.l    d0
  866.     bmi    1f            * 数字エラー
  867.     move.w    d0,d2
  868.     * ファイル名読みだし->fopen
  869.     pea    32.w            * 通常ファイルとして作成
  870.     move.l    a2,-(sp)        * fname
  871.     * (a2)~はファイルなのでEOSがない
  872. @@:    cmp.b    #' '+1,(a2)+        * そこで$1aまたは$0d/$0aをEOSにする
  873.     bpl    @b
  874.     clr.b    -1(a2)            * EOS
  875.     DOS    _CREATE
  876.     addq.w    #8,sp
  877.     move.w    d0,fp            * fp
  878.     bmi    DWSERR            * error
  879.     * 読みとり
  880.     move.l    WriteAD(pc),-(sp)    * 書き込みルーチンを保存
  881.     move.l    #FileWT,WriteAD        * ここで使う書き込みルーチンを設定
  882.     * d1.l <- x,y / d2.w <- size
  883.     bsr    API_Read        * -> d0.l : 読みとった文字数
  884.     move.l    (sp)+,WriteAD        * 書き込みルーチンを戻す
  885.     * ファイルクローズ
  886.     move.l    d0,-(sp)        * d0保存
  887.     move.w    fp,-(sp)
  888.     DOS    _CLOSE
  889.     addq.w    #2,sp
  890.     move.l    (sp)+,d0        * d0復帰
  891. 1:
  892.     rts
  893.  
  894. DWSERR:
  895.     moveq.l    #-1,d0
  896.     rts
  897.  
  898. FileWT:
  899. * ファイル書き込みルーチン
  900. * ReadSize1から呼び出される
  901.     move.l    4(sp),d0    * 文字コード
  902.     move.w    d0,d1        * push d0
  903.     cmp.w    #255,d1
  904.     bls    1f        * 1バイト文字
  905.     * 2バイト文字である
  906.     * 分割して出力
  907.     move.w    d0,-(sp)
  908.     move.b    (sp)+,d0    * d0.l.h.b -> d0.l.l.b
  909.     bsr    1f        * 上位バイト出力
  910.     move.b    d1,d0        * 下位バイト出力
  911. 1:    move.w    fp,-(sp)
  912.     move.w    d0,-(sp)
  913.     DOS    _FPUTC
  914.     addq.w    #4,sp
  915.     moveq.l    #0,d0        * ok
  916.     rts
  917.  
  918. *********************************************************************
  919. * ワーク2
  920. *********************************************************************
  921. * ここに置くワークは、常駐後に使われるもの
  922. * これらのワークエリアは常駐後に利用可能になるので、
  923. * 以下の非常駐ルーチンからは参照しないこと
  924.  
  925. * 常駐後に非常駐部分をワークエリアにする定義
  926. * 必ずevenになるようにすること
  927. fpsz        equ    2        * .dc.w    0
  928. fbsz        equ    2*16        * .ds.b 2*16
  929.  
  930. fp:                    * ファイルポインタ
  931. fb        equ    fp+fpsz        * フォントバッファー
  932. fb_end        equ    fb+fbsz
  933.  
  934. *********************************************************************
  935. * ワークエリア転送ルーチン
  936. *********************************************************************
  937. * ワークエリアを低位メモリーに取るとき、mallocではなく常駐メモリーを多く取って
  938. * プログラムの後ろに付ける。これは、メモリーの分断を防ぐためである。
  939. * が、KSDと違ってGMDは初期化時にワークエリアを使うため、そのまま
  940. * プログラムの後ろ(KEEP_ENDから)に取ることはできない。
  941. * 従って、次の手順を取る。
  942. * (1)/Hに関わらずMALLOC2で高位メモリーにワークを取る
  943. *  初期化中は、このワークエリア内で処理する。
  944. *  /Hの時はこれで終わる。/Hでないときは、この転送ルーチンへ入る。
  945. * (2)スタックポインターを初期状態に戻す
  946. * (3)KEEP_ENDからにワークエリア内容をすべて転送する。
  947. * (4)Zcodes/Hcodesのアドレスを変更する
  948. * (5)先のワークエリアを解放する
  949. * このルーチンそのものは常駐後にfbになる。
  950. *
  951. TrnsWork:
  952. * /hがないとき+常駐終了時のみここにくる
  953. * a0,a2<- 元のZcodes
  954. * a1   <- KEEP_END
  955. * d0.l <- ワークエリアサイズ(.w*2単位分)
  956. * d1.l <- 常駐サイズ
  957. * d7.l <- exit code
  958.     * 転送
  959. @@:    move.l    (a0)+,(a1)+    * 元Zcodes~[.w*2]->KEEP_END
  960.     dbra    d0,@b
  961.     * 高位メモリーワーク解放
  962.     pea    (a2)        * Zcodes
  963.     DOS    _MFREE
  964.     addq.w    #4,sp        * めんどうなのでエラー処理は省略
  965.     *
  966.     tst.b    fdev        * DEVICE=?
  967.     beq    ComEnd        * No
  968.     * デバイスドライバー
  969.     moveq.l    #0,d0        * エラー無し
  970.     rts
  971. *
  972. ComEnd:    * コマンドライン
  973.     move.w    d7,-(sp)    * exit(?)
  974.     move.l    d1,-(sp)    * 常駐サイズ
  975.     DOS    _KEEPPR
  976. TrnsWorkEnd:
  977.  
  978. *--------------------------------------------------------------------
  979. * 転送ルーチンがfbのサイズより小さいときはfbの最後がKEEP_END、
  980. * 逆の時は転送ルーチンの最後がKEEP_END
  981.  
  982. *.if TrnsWorkEnd .gt. fb_end
  983. *KEEP_END    equ    TrnsWorkEnd
  984. *.else
  985. KEEP_END    equ    fb_end
  986. *.endif
  987.         * 常駐固定部分最後+1
  988.  
  989. *********************************************************************
  990. *    非常駐ルーチン
  991. *********************************************************************
  992. * 初期化ルーチン(デバイスドライバー)
  993. *********************************************************************
  994. * 外部参照
  995.  
  996.     .xref    _DevCheck
  997.     .xref    _DevCheck2
  998.     .xref    SetDevLink
  999.     .xref    ResetDevLink
  1000.  
  1001. *--------------------------------------------------------------------
  1002. * 初期化ルーチンは、コマンドラインから起動の時はユーザーモードで、
  1003. * デバイスドライバーの時はスーパーバイザーモードで走る(はず)。
  1004. * 本当は、デバイスドライバー常駐のものを操作する時のため、
  1005. * ここでスーパーバイザーモードにしてからInitSubを呼び出したい。
  1006. * しかしそうすると、setblockがエラーを出してしまう。
  1007. * したがって、複雑になるが、InitSub中で必要時のみスーパーバイザーにする。
  1008. *--------------------------------------------------------------------
  1009.  
  1010. main:    * コマンドライン常駐
  1011. *    clr.b    fdev        * コマンドライン組み込み
  1012.     move.l    sp,oldstack    * 元のスタック保存
  1013.     lea    initsp(pc),sp    * 初期化中用のスタックに設定
  1014.                 * PROGRAM=の時スタックオーバーを起こすのでスタックを変更しておく
  1015.     bsr    InitSub        * 初期化
  1016.     move.l    d0,d7        * exit code保存
  1017.     tst.l    d1        * 常駐サイズあり?
  1018.     bne    @f        * Yes
  1019.     * 常駐以外終了
  1020.     move.l    oldstack(pc),sp    * スタックを戻す
  1021. 1:    move.w    d7,-(sp)    * exit(?)
  1022.     DOS    _EXIT2
  1023. *
  1024. @@:    * デバイスリンクに入り込む
  1025.     lea    DevHead(pc),a0
  1026.     bsr    SetDevLink
  1027.     *
  1028.     * 常駐終了
  1029.     move.l    oldstack(pc),sp    * スタックを戻す
  1030.                 * スタックを戻すのでこれ以降、深いスタックを使わないこと
  1031.     tst.b    Fbmode        * 高位メモリー?
  1032.     bne    ComEnd        * Yes
  1033. WrkChg:    * 低位メモリーの時
  1034.     * ワークエリアアドレス変更
  1035.     * TrnsWorkを小さくするために、できるだけこちらに置いている
  1036.     move.l    Zcodes(pc),a2    * 元のZcodes保存
  1037.     lea    KEEP_END(pc),a1
  1038.     move.l    a1,Zcodes    * ZcodesをKEEP_ENDに変更
  1039.     move.w    Zall(pc),d0
  1040.     add.w    d0,d0        * Zcodes[]は.w;全角文字数は<8000なので大丈夫
  1041.     add.w    d0,a1        * s160も入れるので*2
  1042.     add.w    d0,a1
  1043.     move.l    a1,Hcodes    * Hcodes=&Zcodes[Zall*2*2]
  1044.     *
  1045.     lea    KEEP_END(pc),a1    * (a0) -> (a1)
  1046.     move.l    a2,a0        * a0=元のZcodes(復帰)
  1047.     move.l    ZHall(pc),d0    * 転送サイズ(.l=.w*2単位)
  1048.     subq.l    #1,d0        * -1 for dbra
  1049.     bra    TrnsWork
  1050.  
  1051. *--------------------------------------------------------------------
  1052.  
  1053. Dev_init:            * デバイスドライバ:初期化
  1054.     st.b    fdev        * DEVICE=組み込み
  1055.     bsr    ChangeLine    * コマンドライン変換
  1056.     pea    CrLf(pc)
  1057.     DOS    _PRINT        * 1行改行してからメッセージを出す
  1058.     addq.w    #4,sp
  1059.     *
  1060.     lea    cline0(pc),a2
  1061.     bsr    InitSub        * 初期化
  1062.     tst.l    d1
  1063.     beq    @f        * 常駐以外終了
  1064.     * 常駐終了
  1065.     add.l    #DevHead,d1    * d1<-常駐部最終アドレス
  1066.     move.l    d1,14(a5)
  1067.     *
  1068.     tst.b    Fbmode        * 高位メモリー?
  1069.     beq    WrkChg        * No -> 転送へ
  1070. @@:
  1071.     rts
  1072.  
  1073. * init時のd0.l<>0は白帯にならずに組み込めないメッセージとなる
  1074. *
  1075. *--------------------------------------------------------------------
  1076.  
  1077. PrintDevName:
  1078. * デバイス名表示
  1079. * 改行付き
  1080.     bsr    PrintDevName0
  1081.     pea    CrLf(pc)
  1082.     DOS    _PRINT
  1083.     addq.w    #4,sp
  1084.     rts
  1085.  
  1086. PrintDevName0:
  1087. * デバイス名表示
  1088. * エラー表示のため改行しない
  1089. * a0/d1は破壊してはいけない
  1090.     movem.l    a0/d1,-(sp)
  1091.     *
  1092.     pea    DeviceMes(pc)
  1093.     DOS    _PRINT
  1094.     addq.w    #4,sp
  1095.     *
  1096.     lea.l    DevName-DevHead(a0),a0
  1097.     moveq.l    #0,d0        * for .b = .w
  1098.     moveq.l    #8-1,d1        * デバイス名は8文字まで
  1099. @@:    move.b    (a0)+,d0
  1100.     move.w    d0,-(sp)
  1101.     DOS    _PUTCHAR
  1102.     cmp.w    #' ',(sp)+    * スペースを1つ表示したら終了
  1103.     dbeq    d1,@b
  1104.     *
  1105.     movem.l    (sp)+,d1/a0
  1106.     rts
  1107.  
  1108. *********************************************************************
  1109. * フォントハッシュ用意
  1110. *********************************************************************
  1111.  
  1112. CheckZMoji:
  1113. * そのコードの全角文字が存在するかどうかを調べる
  1114. * Zhaniでもある程度存在しない文字は省いてある(それを踏まえてのルーチン)
  1115. * d4.w=code -> z=1:存在する , z=0:存在しない
  1116.     * c1=1バイト目(d4.h.b) , c2=2バイト目(d4.l.b)
  1117.     * c1<$81,$85~$87,>=$edは存在しない
  1118.     * c1=$ec で c2>=$9fは存在しない
  1119.     * c1=$88,$eb で c2=$40~$9eは存在しない
  1120.     * 2バイト目チェック
  1121.     * $40~$fcがある ただし $7fはない
  1122.     cmp.b    #$40,d4        * c2<$40?
  1123.     bcs    @f        * Yes -> 存在しない
  1124.     cmp.b    #$fc,d4        * c2>$fc?
  1125.     bhi    @f        * Yes -> 存在しない
  1126.     cmp.b    #$7f,d4        * c2==$7f?
  1127.     beq    @f        * Yes -> 存在しない
  1128. okkanji:    * <- 外部から参照される
  1129.     moveq.l    #0,d0        * コードが存在するの印(Z=1)
  1130.     rts
  1131. *
  1132. @@:
  1133.     moveq.l    #1,d0        * コードがおかしいの印(Z=0)
  1134.     rts
  1135.  
  1136. *--------------------------------------------------------------------
  1137.  
  1138.     .even
  1139. Zhani:    * 全角文字範囲
  1140.     * 1バイト目が存在しないページは与えないこと
  1141.     *       start,end
  1142.     .dc.w    $889f,$9872    * 第1水準
  1143.     .dc.w    $824f,$8396    * 英数字かな
  1144.     .dc.w    $8141,$824e    * 記号(全角スペースを除く)
  1145.     .dc.w    $8397,$84fc    * 非漢字
  1146.     .dc.w    $9873,$9ffc    * 第2水準(1)
  1147.     .dc.w    $e040,$eafc    * 第2水準(2)
  1148.     .dc.w    $eb9f,$ec9e    * 全角外字
  1149.     .dc.w    0        * end of table
  1150.  
  1151. Hhani:    * 半角文字範囲(空白は除く)
  1152.     * 半角は存在チェックをしないので、存在する文字のみ与えること
  1153.     *       start,end
  1154.     .dc.w    $0021,$007e    * 1バイト半角
  1155.     .dc.w    $00a1,$00df    * 1バイト半角カタカナ
  1156.     .dc.w    $80a6,$80dd    * 1/2角平仮名
  1157.     .dc.w    $f021,$f07e    * 上付き
  1158.     .dc.w    $f0a1,$f0df
  1159.     .dc.w    $f1a6,$f1dd    * 上付き平仮名
  1160.     .dc.w    $f221,$f27e    * 下付き
  1161.     .dc.w    $f2a1,$f2df
  1162.     .dc.w    $f3a6,$f3dd    * 下付き平仮名
  1163.     .dc.w    $f420,$f4ff    * 半角外字(表示可能なものだけ)
  1164.     .dc.w    $f520,$f5ff
  1165.     .dc.w    0        * end of table
  1166.  
  1167. * 文字数
  1168. * InitReadCharだけでなくInitSubでも読み出す
  1169. Zall    .dc.w    0    * 全角文字数
  1170. Hall    .dc.w    0    * 半角文字数
  1171. ZHall    .dc.l    0    * 全角+半角文字数(.wで十分だが後の処理のため.lにする)
  1172. WKsize    .dc.l    0    * ZHall*sizeof(word)*2 : 可変ワークエリアサイズ
  1173.  
  1174. RWTable    * Read/Write Table
  1175.     *    size,bufferの2データがセット
  1176.     .dc.l    2,Zall        * 2=sizeof(?all)
  1177.     .dc.l    2,Hall
  1178.     .dc.l    (ZAREA+HAREA)*(1+2),Zsumx    * Zsumx,Hsumx,Ztops,Htopsを一気読み書き
  1179. RWTBLSZ    .equ    3        * このテーブルのデータ数
  1180.  
  1181. HSIZE    equ    8        * ヘッダーサイズ : 2*longword(変えないこと)
  1182. *
  1183. Header:    * ファイルヘッダー(サイズ=HSIZE)
  1184.     .dc.b    'GMD'
  1185. Hver:    .dc.b    0        * メジャーバージョン=Ver1+'0'が入る
  1186.     .dc.b    $0d,$0a,$1a,$00
  1187. *
  1188. HBuff    .ds.b    HSIZE        * ヘッダー読み込み用バッファー
  1189.     .even
  1190.  
  1191. *--------------------------------------------------------------------
  1192.  
  1193. LSumH:
  1194. * 半角文字フォントハッシュ計算
  1195. * a1 <- font adrs (fb)
  1196. * a2は破壊しないこと
  1197. * -> d0.l.w : ハッシュ値(s16) , NOCHR=空白文字である(s160不定)
  1198. *    d0.h.w : 第2指標(s160)
  1199.     move.l    d7,-(sp)
  1200.     *
  1201.     lea    1(a1),a0    * p=&fb->buffer[1]
  1202.     moveq.l    #0,d7        * s160=0
  1203.     moveq.l    #0,d2        * s16=0
  1204.     moveq.l    #11-1,d0    * 1~11line
  1205. @@:    moveq.l    #0,d1        * for .b -> .w
  1206.     move.b    (a0),d1        * s16+=*p++
  1207.     add.w    d1,d2
  1208.     move.b    (a0)+,d1    * eor.b    (a0),d1が出来ないので
  1209.     eor.b    d1,d7        * s160^=*p
  1210.     dbra    d0,@b
  1211.     *
  1212.     tst.w    d2        * s16=0?
  1213.     bne    @f        * no = 空白ではない
  1214.     tst.b    (a1)        * line 0
  1215.     bne    @f        * <>0
  1216.     * line 1~11までは0なので再計算しない
  1217.     moveq.l    #-1,d0        * 空白の印:move.w #NOCHR,d0
  1218.     tst.l    12(a1)        * line 12,13,14,15
  1219.     beq    1f        * ==0 : 空白である
  1220. @@:    move.w    d7,d0        * s160
  1221.     lsl.w    #8,d0        * s160の値を上位8ビットへ移動する&下位8ビット=0
  1222.     swap    d0        *    .h.w
  1223.     move.w    d2,d0        * s16.l.w
  1224.     *
  1225. 1:    move.l    (sp)+,d7
  1226.     rts
  1227.  
  1228. *--------------------------------------------------------------------
  1229.  
  1230. CalcSumSubZ:
  1231. * 全角文字チェック
  1232. * d5.w <- mode
  1233.     movem.l    d3-d7/a3-a6,-(sp)
  1234.     move.w    #ZMASK,d3        * mask
  1235.     lea    Zhani(pc),a1        * 文字コード範囲群
  1236.     move.l    Zcodes(pc),a2
  1237.     lea    Ztops(pc),a3
  1238.     lea    Zsumx(pc),a4
  1239.     lea    LSum(pc),a5        * d0-d2/a0-a1破壊
  1240.     lea    CheckZMoji(pc),a6    * d0破壊
  1241.     bra.s    @f
  1242.  
  1243. CalcSumSubH:
  1244. * 半角文字チェック
  1245. * d5.w <- mode
  1246.     movem.l    d3-d7/a3-a6,-(sp)
  1247.     move.w    #HMASK,d3        * mask
  1248.     lea    Hhani(pc),a1        * 文字コード範囲群
  1249.     move.l    Hcodes(pc),a2
  1250.     lea    Htops(pc),a3
  1251.     lea    Hsumx(pc),a4
  1252.     lea    LSumH(pc),a5        * d0-d2/a0-a1破壊
  1253.     lea    okkanji(pc),a6        * ダミー関数 : 常時checkmoji(c)=0 : "その文字はある"を返す
  1254. @@:    *
  1255.     swap    d3        * d3.h.w=mask
  1256.     moveq.l    #0,d6        * all=0
  1257. 3:    move.w    (a1)+,d4    * d4.w=st
  1258.     beq    5f        * -> end
  1259.     move.w    (a1)+,d3    * d3.w=ed
  1260.     *
  1261.     move.l    a1,d7        * a1保存
  1262. 1:    * 文字判定
  1263.     jsr    (a6)        * check_moji(d4) : d0破壊
  1264.     bne    2f        * この文字は存在しない
  1265.     *
  1266.     move.w    d4,d1        * c
  1267.     bsr    FNTADR        * d0,d1,d2破壊
  1268.     move.l    d0,a1        * ->Font adrs(from ROM)
  1269.     jsr    (a5)        * bsr LSum : d0-d2/a0-a1破壊
  1270.     cmp.w    #NOCHR,d0    * 空白フォント?
  1271.     beq    2f        * Yes
  1272.     * d0.w=s16
  1273.     swap    d3
  1274.     and.w    d3,d0        * s16&HMASK
  1275.     swap    d3
  1276.     lea    (a4,d0.w),a0    * sumx[s16]
  1277.     tst.w    d5        * mode=0?
  1278.     beq    @f        * Yes
  1279.     *
  1280.     moveq.l    #0,d1        * for .b -> .w
  1281.     move.b    (a0),d1        * d1.w=sumx[s16]
  1282.     add.w    d1,d1
  1283.     add.w    d1,d1        * codesはword*2だから
  1284.     add.w    d0,d0        * topsはwordだから
  1285.     add.w    (a3,d0.w),d1    * d1.w=tops[s16]+sumx[s16]*(.w*2)
  1286.     swap    d0        * d0.h.w=s160
  1287.     move.w    d0,(a2,d1.w)    * codes[d1.w+0]=s160(先に比較するので先に格納する)
  1288.     move.w    d4,2(a2,d1.w)    * codes[d1.w+2]=c
  1289.     *
  1290. @@:    addq.b    #1,(a0)        * sumx[s16]++
  1291.     addq.w    #1,d6        * all++
  1292. 2:    addq.w    #1,d4        * c++
  1293.     cmp.w    d3,d4        * <=ed?
  1294.     bls    1b        * Yes
  1295.     *
  1296.     move.l    d7,a1        * a1復帰
  1297.     bra    3b
  1298. *
  1299. 5:    move.l    d6,d0        * d0.w <- all
  1300.     tst.w    d5        * mode?
  1301.     movem.l    (sp)+,d3-d7/a3-a6
  1302.     rts
  1303.  
  1304. *----------------------------------
  1305.  
  1306. CalcSum:
  1307. * d5.w <- mode (0/1)
  1308.     * Zsumx+Hsumxをクリア
  1309.     lea    Zsumx(pc),a0
  1310.     move.w    #(ZAREA+HAREA)/4-1,d0    * .l単位で消すから(moveqではあふれるので駄目)
  1311. @@:    clr.l    (a0)+
  1312.     dbra    d0,@b
  1313.     *
  1314.     clr.l    a1
  1315.     IOCS    _B_SUPER    * super visor mode
  1316.     move.l    d0,-(sp)
  1317.     *
  1318.     * 全角文字計算
  1319.     bsr    CalcSumSubZ    * -> d0(all)
  1320.     bne    @f
  1321.     move.w    d0,Zall
  1322. @@:    * 半角文字計算
  1323.     bsr    CalcSumSubH    * -> d0(all)
  1324.     bne    @f
  1325.     move.w    d0,Hall
  1326. @@:    *
  1327.     move.l    (sp)+,d0
  1328.     bmi    @f        * 元からsuper visorであった
  1329.     move.l    d0,a1
  1330.     IOCS    _B_SUPER    * user mode
  1331. @@:
  1332.     rts
  1333.  
  1334. *----------------------------------
  1335.  
  1336. ReadWriteSub:
  1337. * d4.w <- fp
  1338. * d2.w <- mode (0=Read,1=Write)
  1339. * -> d0.b (0=ok,-1=error)
  1340.     lea    RWTable(pc),a0
  1341.     moveq.l    #RWTBLSZ-1,d1        * 読み込みデータ数-1 for db??
  1342. @@:    move.l    (a0)+,a1
  1343.     move.l    a1,-(sp)        * size
  1344.     move.l    (a0)+,-(sp)        * buffer
  1345.     move.w    d4,-(sp)        * fp
  1346.     tst.w    d2            * WriteMode?
  1347.     bne    2f            * Yes
  1348.     * ReadMode
  1349.     DOS    _READ
  1350.     bra.s    3f
  1351.     *
  1352. 2:    * WriteMode
  1353.     DOS    _WRITE
  1354. 3:    lea    4*2+2(sp),sp
  1355.     cmp.l    d0,a1            * =size?
  1356.     dbne    d1,@b            * 読み書きサイズが実際のそれと異なる時はエラー
  1357.     *
  1358.     sne    d0            * <>sizeの時<>0.b
  1359.     rts
  1360.  
  1361. *----------------------------------
  1362.  
  1363. Fclose:
  1364. * 単なるファイルクローズ
  1365. * d4.w <- fp
  1366.     move.w    d4,-(sp)    * fp
  1367.     DOS    _CLOSE
  1368.     addq.w    #2,sp
  1369.     rts
  1370.  
  1371. *----------------------------------
  1372.  
  1373. SetHashWork:
  1374. * -> d1.l : <0=error , >0=ok:Zcodes
  1375. *           mi           pl (0はない)
  1376.     * 全角+半角で一気に処理する
  1377.     moveq.l    #0,d0        * for .w -> .l
  1378.     move.w    Zall(pc),d0    * Zall
  1379.     add.w    Hall(pc),d0    * +Hall -> ZHall
  1380.     move.l    d0,ZHall    * 記録
  1381.     
  1382.     * メモリー確保(d0)
  1383.     add.l    d0,d0        * ZHall*sizeof(word)
  1384.     add.l    d0,d0        *                   *2=ワークエリアサイズ
  1385.     move.l    d0,WKsize        * 記録
  1386.     move.l    d0,-(sp)    * size
  1387.     move.w    #2,-(sp)    * ここでは常に高位メモリーに確保
  1388.     DOS    _MALLOC2
  1389.     addq.w    #6,sp
  1390.     move.l    d0,d1        * d1=adrs
  1391.     bmi    @f        * メモリーが確保できない(d1<0)
  1392.     *
  1393.     move.l    d1,Zcodes    * Zcodes=m
  1394.     moveq.l    #0,d0        * for .w -> .l
  1395.     move.w    Zall(pc),d0
  1396.     add.l    d0,d0        * Zcodesはword*2だから
  1397.     add.l    d0,d0
  1398.     add.l    d1,d0        * m+Zall(word*2)
  1399.     move.l    d0,Hcodes    * Hcodes=&Zcodes[Zall*2];
  1400.     * d1>0=Zcodes
  1401. @@:
  1402.     rts
  1403.  
  1404. *----------------------------------
  1405.  
  1406. ReadHashFile    macro
  1407. * ハッシュファイル読みとり
  1408. local    L1,L2,L3,L4,L5
  1409. * a4 <- fname
  1410.     * ファイルオープン
  1411.     clr.w    -(sp)        * read mode
  1412.     pea    (a4)        * fname
  1413.     DOS    _OPEN
  1414.     addq.w    #6,sp
  1415.     move.l    d0,d4        * fp
  1416.     bmi    IRC2        * <0=そのファイルはない->テーブル作成
  1417.     * ヘッダー読み込み
  1418.     pea    HSIZE.w        * size
  1419.     pea    HBuff(pc)    * buf
  1420.     move.w    d4,-(sp)    * fp
  1421.     DOS    _READ
  1422.     lea    10(sp),sp
  1423.     cmp.l    #HSIZE,d0    * ==size?
  1424.     bne    L2        * 読み込めない
  1425.     * ヘッダーチェック
  1426.     * 8バイトなので2*longwordでチェックする
  1427.     lea    Header(pc),a0
  1428.     lea    HBuff(pc),a1
  1429.     cmp.l    (a0)+,(a1)+
  1430.     bne    L5
  1431.     cmp.l    (a0)+,(a1)+
  1432.     beq    L4
  1433. L5:    * ヘッダーが異常
  1434.         bsr    Fclose
  1435.         moveq.l    #-3,d0    * return($fffd)
  1436.         rts
  1437.     *
  1438. L4:    * ファイル読みとり
  1439.     moveq.l    #0,d2        * mode=2:read
  1440.     bsr    ReadWriteSub    * -> d0.b(ret)
  1441.     move.b    d0,d3        * ret=
  1442.     bne    L1        * ret
  1443.     * ハッシュワークを確保する
  1444.     bsr    SetHashWork    * -> d1.l(Zcodes)
  1445.     bpl    L3        * OK
  1446.         * メモリーが確保できない
  1447.         bsr    Fclose
  1448.         moveq.l    #0,d0    * return(0)
  1449.         rts
  1450.     *
  1451. L3:    move.l    WKsize(pc),d0    * ZHall*sizeof(word)
  1452.     move.l    d0,d2        * size保存
  1453.     move.l    d0,-(sp)    * size
  1454.     move.l    d1,-(sp)    * Zcodes
  1455.     move.w    d4,-(sp)    * fp
  1456.     DOS    _READ
  1457.     lea    10(sp),sp
  1458.     cmp.l    d0,d2        * ==size?
  1459. L2:    sne    d3        * ret : d3.b <- $00/$ff
  1460. L1:    bsr    Fclose
  1461.     tst.b    d3        * ret?
  1462.     beq    IRC1        * No
  1463.     moveq.l    #-2,d0        * return($fffe)
  1464.     rts
  1465.     endm
  1466.  
  1467. *----------------------------------
  1468.  
  1469. WriteHashFile    macro
  1470. * ハッシュファイル書きだし
  1471. local L1,L2,L3
  1472. * a4 <- fname
  1473.     * ファイル作成
  1474.     pea    32.w        * 通常ファイルとして作成
  1475.     move.l    a4,-(sp)    * fname
  1476.     DOS    _CREATE
  1477.     addq.w    #8,sp
  1478.     move.l    d0,d4        * fp
  1479.     bmi    L1        * <0=error
  1480.     * ヘッダー書き出し
  1481.     pea    HSIZE.w        * size
  1482.     pea    Header(pc)    * buf
  1483.     move.w    d4,-(sp)    * fp
  1484.     DOS    _WRITE
  1485.     lea    10(sp),sp
  1486.     cmp.l    #HSIZE,d0    * ==size?
  1487.     bne    L3        * 書き込めない
  1488.     *
  1489.     * ファイル書きだし
  1490.     moveq.l    #1,d2        * mode=1:write
  1491.     bsr    ReadWriteSub
  1492.     move.b    d0,d3        * ret=
  1493.     bne    L2
  1494.     *
  1495.     move.l    WKsize(pc),d0    * ZHall*sizeof(word)
  1496.     move.l    d0,d2        * size保存
  1497.     move.l    d0,-(sp)    * size
  1498.     move.l    Zcodes(pc),-(sp)    * buf
  1499.     move.w    d4,-(sp)    * fp
  1500.     DOS    _WRITE
  1501.     lea    10(sp),sp
  1502.     cmp.l    d0,d2        * ==size?
  1503. L3:    sne    d3        * d3.b <- $00/$ff
  1504. L2:    bsr    Fclose
  1505.     tst.b    d3        * ret?
  1506.     beq    IRC1        * No
  1507.     * ファイル作成時エラー
  1508.     * 作りかけのファイルを削除する
  1509.     * CREATしているから問題ない
  1510.     move.l    a4,-(sp)
  1511.     DOS    _DELETE
  1512.     addq.w    #4,sp
  1513. L1:    moveq.l    #-1,d0            * return($ffff)
  1514.     rts
  1515.     endm
  1516.  
  1517. *----------------------------------
  1518. * codes内でのハッシュ毎の先頭位置を決める→tops[]
  1519.  
  1520. CalcTops:
  1521. * a0   <- sumx
  1522. * a1   <- tops
  1523. * d0.w <- AREAサイズ-1 (-1 for dbra)
  1524.     moveq.l    #0,d2        * p=0
  1525. @@:    move.w    d2,(a1)+    * tops[i].w=p
  1526.     moveq.l    #0,d1        * for .b -> .w
  1527.     move.b    (a0)+,d1    * sumxは.b
  1528.     add.w    d1,d1
  1529.     add.w    d1,d1        * *4(codes[]は.w*2)
  1530.     add.w    d1,d2
  1531.     dbra    d0,@b
  1532.     rts
  1533.  
  1534. *----------------------------------
  1535.  
  1536. InitReadChar:
  1537. * int InitReadChar(fname)
  1538.     move.b    Ver1(pc),d0    * メジャーバージョンを入れる
  1539.     add.b    #'0',d0        * +'0'するため、上限は$4e('0'~$7eまで)となるが
  1540.     move.b    d0,Hver        * そこまでバージョンが上がることはなかろう
  1541.     *
  1542.     move.l    4(sp),a4    * fname
  1543.     tst.b    (a4)
  1544.     beq    IRC2
  1545.     * ファイルの指定があるとき
  1546.     ReadHashFile        * ハッシュファイル読み込み
  1547.     *
  1548. IRC2:    * メッセージ表示
  1549.     pea    TableMakeMes(pc)
  1550.     DOS    _PRINT
  1551.     addq.w    #4,sp
  1552.     *
  1553.     * (1)sumの計算(その分布調査)
  1554.     moveq.l    #0,d5        * mode
  1555.     bsr    CalcSum
  1556.     *
  1557.     * (2)全文字分のコード表ワークエリア確保
  1558.     bsr    SetHashWork    * -> d1.l
  1559.     bpl    @f        * OK
  1560.     * メモリー確保出来ないエラー
  1561.     moveq.l    #0,d0        * return(0)
  1562.     rts
  1563.     *
  1564. @@:    * (3)コード表ワークのsum毎の先頭位置を決める
  1565.     lea    Zsumx(pc),a0
  1566.     lea    Ztops(pc),a1
  1567.     move.w    #ZAREA-1,d0    * -1 for dbra
  1568.     bsr    CalcTops
  1569.     *
  1570.     lea    Hsumx(pc),a0
  1571.     lea    Htops(pc),a1
  1572.     move.w    #HAREA-1,d0    * -1 for dbra
  1573.     bsr    CalcTops
  1574.     *
  1575.     * (4)もう一度sumを計算し、今度はコード表に格納する
  1576.     moveq.l    #1,d5        * mode
  1577.     bsr    CalcSum
  1578.     *
  1579.     * メッセージ消去
  1580.     pea    TableClrMes(pc)
  1581.     DOS    _PRINT
  1582.     addq.w    #4,sp
  1583.     *
  1584.     * (5)ファイル指定がある時は、そのファイルを作成する
  1585.     move.l    4(sp),a4    * fname
  1586.     tst.b    (a4)
  1587.     beq    IRC1        * ファイル名指定がない
  1588.     * ファイルの指定があるとき
  1589.     WriteHashFile        * ハッシュファイル書きだし
  1590.     *
  1591. IRC1:    move.l    ZHall(pc),d0    * return(ZHall)
  1592.     rts
  1593.  
  1594. *********************************************************************
  1595.  
  1596. ChangeLine:
  1597.     * DEVICE=形式のパラメーターをコマンドライン型に変換する
  1598.     * 読み取りルーチン共用化のため
  1599.     move.l    18(a5),a0    * 元のコマンドライン
  1600.     * 最初の00まではプログラム名なので飛ばす
  1601. @@:    tst.b    (a0)+
  1602.     bne    @b
  1603.     *
  1604.     lea    cline(pc),a2    * 変換後ライン
  1605.     moveq.l    #0,d1        * length
  1606. CL1:    tst.b    (a0)
  1607.     beq    CLend        * 0,0で終了
  1608. @@:    addq.l    #1,d1        * len++
  1609.     move.b    (a0)+,(a2)+
  1610.     bne    @b
  1611.     * 0をスペースに直す
  1612.     move.b #' ',-1(a2)
  1613.     bra.s    CL1
  1614. *
  1615. CLend:    clr.b    (a2)        * EOS
  1616.     move.b    d1,cline0
  1617.     rts
  1618.  
  1619. *--------------------------------------------------------------------
  1620. * コマンドライン解析(a2=コマンドライン)
  1621. * この中ではa0は壊さないこと(プロセス管理ポインタを参照するため)
  1622.  
  1623. ChkARG:
  1624.     clr.b    HashName    * ファイル名指定がないときのため(EOS)
  1625.     tst.b    (a2)+        * コマンドラインサイズ = 0?
  1626.     bne    arglp        * No
  1627.     * コマンドラインがない(プログラム名のみ)
  1628.     * GMDではエラーにならない
  1629.     move.w    #$ff00,d0    * 注意(.b=0,.w!=0)
  1630.     rts
  1631. *
  1632. arglp:
  1633. @@:    * 空白飛ばし
  1634.     move.b    (a2)+,d0
  1635.     cmp.b    #' ',d0
  1636.     beq    @b
  1637.     cmp.b    #$09,d0        * TAB
  1638.     beq    @b
  1639.     subq.w    #1,a2        * a2が1つ進んでいるので戻す
  1640.     *
  1641.     tst.b    d0        * end?
  1642.     beq    eos        * Yes
  1643.     * オプションは -? or /?
  1644.     cmp.b    #'-',d0
  1645.     beq    chkopt
  1646.     cmp.b    #'/',d0
  1647.     beq    chkopt
  1648. getarg:    * オプション以外の引数はフォントハッシュファイル名とみなす
  1649.     * HashNameにそれを転送
  1650.     lea.l    HashName(pc),a3    * bssなので(pc)にしない...本当は
  1651. @@:    move.b    (a2)+,d0
  1652.     cmp.b    #' ',d0        * SPCがあったら終わり
  1653.     beq    @f
  1654.     cmp.b    #$09,d0        * TABがあったら終わり
  1655.     beq    @f
  1656.     move.b    d0,(a3)+
  1657.     bne    @b
  1658. eos:    * EOSを入れたら終了(この後にオプションはない)
  1659.     moveq.l    #0,d0        * ok(.b=0,.w=0)
  1660.     rts
  1661. *
  1662. @@:    clr.b    (a3)        * EOS
  1663.     bra    arglp        * オプションチェックに戻る
  1664.  
  1665. chkopt:    * オプションチェック
  1666.     addq.w    #1,a2        * skip '-' or '/'
  1667.     move.b    (a2)+,d0
  1668.     beq    argerr        * -/のみでオプションがない
  1669.     and.b    #%11011111,d0    * 大文字化
  1670.     *
  1671.     lea    ComFlags-2(pc),a6    * 後で+2するため-2しておく
  1672.     tst.b    fdev        * DEVICE=?
  1673.     beq    @f        * no
  1674.     * DEVICE=時
  1675.     lea    DevFlags-2(pc),a6    * 後で+2するため-2しておく
  1676. @@:    addq.w    #2,a6
  1677.     tst.b    1(a6)        * Option名
  1678.     beq    argerr        * 全てのオプションと比較終了 -> 規定外オプション
  1679.     cmp.b    1(a6),d0    * オプションチェック
  1680.     bne    @b        * 不一致
  1681.     tst.b    (a6)        * すでにフラグがセットされている?
  1682.     bne    arglp        * Yes : 飛ばす(2重指定なのでargerrにしてもよい)
  1683.     st.b    (a6)        * セット
  1684.     bra    arglp        * コマンドライン処理へ戻る
  1685.  
  1686. argerr:
  1687.     moveq.l    #-1,d0        * エラー(.b<>0)
  1688.     rts
  1689.  
  1690. *--------------------------------------------------------------------
  1691.  
  1692. InitSub:    * 初期化 -> d0.l:status , d1.l=常駐サイズ
  1693. * a5は壊さないこと
  1694.     move.l    a0,d7        * a0保存
  1695.     lea    HashName(pc),a0
  1696.     * バージョン番号文字列作成
  1697.     * a0.l = バッファー
  1698.     moveq.l    #0,d0
  1699.     move.b    Ver1(pc),d0    * 整数桁
  1700.     FPACK    __LTOS        * d0.l(符号つき) -> 10進文字列化
  1701.     move.b    #'.',(a0)+    * 小数点
  1702.     moveq.l    #0,d0
  1703.     move.b    Ver2(pc),d0    * 小数桁
  1704.     FPACK    __LTOS        * d0.l(符号つき) -> 10進文字列化
  1705.     *
  1706.     pea    title1(pc)    * タイトル前半表示
  1707.     DOS    _PRINT
  1708.     pea    HashName(pc)    * バージョン番号
  1709.     DOS    _PRINT
  1710.     pea    title2(pc)    * タイトル後半表示
  1711.     DOS    _PRINT
  1712.     lea    4*3(sp),sp
  1713.     move.l    d7,a0        * a0復帰
  1714.     *
  1715.     bsr    ChkARG        * コマンドライン引数チェック
  1716.     tst.b    d0        * .wではない
  1717.     bne    usage        * 引数がおかしい
  1718.     *
  1719.     * このあたりではa2は破壊しないこと
  1720.     *
  1721.     move.l    a2,-(sp)    * 重要
  1722.     clr.l    -(sp)        * デバイス名格納せず
  1723.     pea    GMDsym(pc)    * 隠しデバイス名
  1724.     bsr    _DevCheck2    * デバイスチェック
  1725.     addq.l    #8,sp
  1726.     move.b    d0,d7        * d7.b :  0=常駐してない(a0=不変=自己メモリーブロック)
  1727.                 *       $ff=常駐している(a0=デバイスヘッダーアドレス=DevHead)
  1728.     move.l    (sp)+,a2    * 重要
  1729.     *
  1730.     tst.b    rflag        * -r : 常駐解除?
  1731.     beq    keep        * no
  1732. *
  1733. * 常駐解除(device=では絶対に来ない)
  1734. *
  1735.     tst.b    d7        * 常駐している?
  1736.     beq    Err_NoKp    * No -> error
  1737.     
  1738.     * DEVICE=で常駐している時は解除不可
  1739.     lea.l    fdev-DevHead(a0),a1
  1740.     IOCS    _B_BPEEK    * スーパーバイザーの中を覗くことがあるため
  1741.     tst.b    d0
  1742.     bne    Err_Dev        * DEVICE=で組み込まれている
  1743.     *
  1744.     * ここに来るのはコマンドライン常駐の時のみ=ksdは必ずユーザーモード領域にいる
  1745.     * 常駐ロックチェック
  1746.     tst.b    JLock-DevHead(a0)    * =0?
  1747.     bne    Err_Lock    * No:常駐ロック中
  1748.     
  1749.     * すでに常駐しているものを解除
  1750.     * ここに来るのはコマンドライン常駐の時のみ
  1751.     move.l    ProcAD-DevHead(a0),-(sp)    * このプロセスの先頭アドレス
  1752.     DOS    _MFREE        * 自己プロセスメモリー解放
  1753.     addq.w    #4,sp
  1754.     tst.l    d0
  1755.     bmi    Err_Kai        * なぜかメモリー解放出来ない時
  1756.     *
  1757.     tst.b    Fbmode        * 高位モード?
  1758.     beq    @f        * No
  1759.     * 高位モードの時のみ:ワークエリアの解放
  1760.     move.l    Zcodes-DevHead(a0),-(sp)    * Zcodes解放
  1761.     DOS    _MFREE
  1762.     addq.w    #4,sp
  1763.     tst.l    d0
  1764.     bmi    Err_WkNk    * なぜかメモリー解放出来ない時
  1765. @@:    * エラーが出た場合、プロセスがなくワークのみが残ることになる。
  1766.     * 非常によろしくない。一言で言えば手抜きである。
  1767.     *
  1768.     * デバイスリンク解除
  1769.     bsr    ResetDevLink    * a0=DevHead
  1770.     *
  1771.     * 常駐解除正常終了
  1772.     pea.l    MesRelease(pc)    * 解除メッセージ
  1773.     DOS    _PRINT
  1774.     addq.w    #4,sp
  1775.     *
  1776.     moveq.l    #0,d1        * 常駐しない
  1777.     moveq.l    #0,d0        * 正常終了:exit(0)
  1778.     rts
  1779. *
  1780. * 常駐
  1781. *
  1782. keep:    tst.b    d7        * すでに常駐している?
  1783.     bne    Err_2Kp        * Yes -> 2重常駐エラー
  1784.     *
  1785.     * デバイス名を変更する時はここで行う
  1786.     tst.b    gflag        * デバイス名を@GMDにする?
  1787.     beq    @f        * No
  1788.         * @MOJI -> @GMD
  1789.         move.b    #'G',DevName+1
  1790.         move.w    #('M'<<8)|'D',DevName+2    * ここはワードで書き込める
  1791.         move.b    #' ',DevName+4
  1792. @@:    * 同名デバイスもない?
  1793.     movem.l    a0-a2,-(sp)    * 重要
  1794.     pea    DevName(pc)
  1795.     bsr    _DevCheck
  1796.     addq.l    #4,sp
  1797.     movem.l    (sp)+,a0-a2    * 重要
  1798.     tst.b    d0
  1799.     bne    Err_DevUse    * 同名デバイスがある
  1800.     * 同名デバイスもない
  1801.     *
  1802.     * 常駐していない->常駐処理
  1803.     tst.b    hflag        * 高位メモリー?
  1804.     sne.b    Fbmode        * Yes -> Fbmode=$ff
  1805.     
  1806.     tst.b    fdev
  1807.     bne    @f        * -> DEVICE=常駐
  1808.     * プログラム起動時にはフリーエリアの全てが起動プログラムに割り当てられているため、
  1809.     * これを必要部分以外解放する。そうしないとMALLOC2が効かない。
  1810.     * DEVICE=のときは不要(MALLOC2出来る)。
  1811.     * a0=プログラムメモリ管理ポインタ
  1812.     * a1=プログラム終了アドレス+1(.data,.bssを含む)
  1813.     lea    MPSIZ(a0),a0    * メモリー管理ポインタ分を飛ばす
  1814.     move.l    a0,ProcAD    * このプロセスの先頭アドレス(!=DevHead)保存
  1815.     sub.l    a0,a1        * 当プログラムサイズ
  1816.     move.l    a1,-(sp)    * 確保する領域サイズ
  1817.     move.l    a0,-(sp)    * 確保する領域の先頭アドレス
  1818.     DOS    _SETBLOCK    * 領域変更
  1819.     addq.w    #4*2,sp
  1820.     tst.l    d0
  1821.     bmi    Err_StBk        * 領域が変更できない時=エラー
  1822. @@:
  1823.     * IOCS _FNTADRのアドレス取得(高速化のため)
  1824.     move.w    #_FNTADR+$100,-(sp)
  1825.     DOS    _INTVCG
  1826.     addq.w    #2,sp
  1827.     move.l    d0,AFNTADR
  1828.     * フォントハッシュ作成
  1829.     movem.l    d1-d5/a0-a4,-(sp)
  1830.     pea    HashName(pc)    * フォントハッシュファイル名
  1831.     bsr    InitReadChar
  1832.     addq.w    #4,sp
  1833.     movem.l    (sp)+,d1-d5/a0-a4
  1834.     cmp.w    #$fffd,d0    * 必ず.wで比較
  1835.     beq    Ferror3        * Header Illegal
  1836.     cmp.w    #$fffe,d0    * 必ず.wで比較
  1837.     beq    Ferror1        * Can't Read
  1838.     bhi    Ferror2        * Can't Write (d0.w=$ffff)
  1839.     tst.w    d0
  1840.     beq    Err_Wrk        * memory不足
  1841.     *
  1842.     move.l    #KEEP_END-DevHead,d1    * 常駐サイズ:本体
  1843.     tst.b    Fbmode        * 高位メモリー?
  1844.     bne    @f        * Yes
  1845.     * 低位メモリーの時はその分を加える
  1846.     add.l    WKsize(pc),d1    * +size
  1847.     * このプロセスの占めるメモリー領域を拡大してワークも入るようにする
  1848.     * 本当は、d1<initsp-DevHead=常駐サイズが元のプログラムサイズより小さくなる
  1849.     * なら次のプロセスメモリーの拡大の前にスタックを元に戻す必要がある。
  1850.     * 拡大したつもりが縮小になり、スタックが領域外に出てしまうためである。
  1851.     * しかし、GMDでは通常は絶対にあり得ないので簡略化してここで行っている
  1852.     move.l    d1,d0
  1853.     add.l    #PSPSIZ-MPSIZ,d0    * プロセス管理ポインタ分も含める
  1854.     move.l    d0,-(sp)        * new size
  1855.     move.l    ProcAD(pc),-(sp)
  1856.     DOS    _SETBLOCK
  1857.     addq.w    #8,sp
  1858.     bmi    Err_Wrk        * メモリー不足
  1859.     *
  1860. @@:    pea    MesRevMode(pc)    * 反転文字読み取りモード表示
  1861.     DOS    _PRINT
  1862.     lea    MesRevOn(pc),a1
  1863.     tst.b    oflag        * 反転文字ON?
  1864.     sne.b    RevMode        * Yes -> RevMode=$ff
  1865.     bne    @f
  1866.     lea    MesRevOff(pc),a1
  1867. @@:    pea    (a1)
  1868.     DOS    _PRINT
  1869.     addq.w    #4*2,sp
  1870.     *
  1871.     pea    MesKeep(pc)    * 常駐メッセージ
  1872.     DOS    _PRINT
  1873.     addq.w    #4,sp
  1874.     lea    DevHead(pc),a0    * このプログラム内を参照
  1875.     bsr    PrintDevName    * デバイス名表示
  1876.     moveq.l    #0,d0        * exit(0)
  1877.     rts
  1878.  
  1879. *--------------------------------------
  1880. * エラー処理
  1881. *--------------------------------------
  1882. Ferror3:    * ハッシュファイルでない
  1883.     lea    ErrIllHash(pc),a0
  1884.     bra.s    @f
  1885. Ferror2:    * ファイルに書けない
  1886.     lea    ErrCantWtHash(pc),a0
  1887.     bra.s    @f
  1888. Ferror1:    * ファイルが読めない
  1889.     lea    ErrCantRdHash(pc),a0
  1890. @@:    bsr    PrintErr
  1891.     lea    HashName(pc),a0        * ファイル名表示
  1892.     bra.s    error
  1893. *
  1894. Err_DevUse:    * デバイス名がすでに使われている
  1895.     lea    DevHead(pc),a0        * このプログラム内を参照
  1896.     bsr    PrintDevName0
  1897.     lea.l    ErrDevUse(pc),a0
  1898.     bra.s    error
  1899. Err_StBk:    * SetBlock出来ない
  1900. *    lea.l    ErrCantKpBuff2(pc),a0
  1901. *    bra.s    error
  1902. Err_Wrk:    * ワークエリアが確保出来ない
  1903.     lea.l    ErrCantKpBuff(pc),a0
  1904.     bra.s    error
  1905. Err_NoKp:    * 常駐していないのに解除しようとした
  1906.     lea.l    ErrNoKumikomi(pc),a0
  1907.     bra.s    error
  1908. Err_2Kp:    * 2重常駐
  1909.     lea    DevHead(pc),a0    * このプログラム内を参照
  1910.     bsr    PrintDevName    * デバイス名表示
  1911.     lea.l    ErrAlreadySet(pc),a0
  1912.     bra.s    error
  1913. *
  1914. Err_WkNk:    * ワークエリアが解放できない
  1915.     lea.l    ErrCantResBuff(pc),a0
  1916.     bra.s    error
  1917. Err_Dev:    * DEVICE=で組み込まれている
  1918.     lea.l    ErrCantDevice(pc),a0
  1919.     bra.s    @f
  1920. Err_Lock:    * 常駐ロックされている
  1921.     lea.l    ErrCantJLock(pc),a0
  1922. @@:    bsr    PrintErr
  1923. Err_Kai:    * 常駐解除不可
  1924.     lea.l    ErrCantRelease(pc),a0
  1925.     bra.s    error
  1926. *
  1927. usage:    * 使用法
  1928.     lea.l    MesUsage(pc),a0
  1929. error:    bsr    PrintErr
  1930.     lea    CrLf(pc),a0
  1931.     bsr    PrintErr
  1932.     *
  1933.     moveq.l    #0,d1        * 常駐しない
  1934.     moveq.l    #2,d0        * exit(2)
  1935.     rts
  1936. *
  1937. PrintErr
  1938. * (a0)エラー出力へメッセージ表示
  1939.     move.w    #2,-(sp)    * STDERR
  1940.     pea.l    (a0)
  1941.     DOS    _FPUTS
  1942.     addq.w    #2+4,sp
  1943.     rts
  1944.  
  1945. *********************************************************************
  1946. * メッセージなど
  1947. *********************************************************************
  1948.  
  1949.     .even
  1950. TableMakeMes:    .dc.b        'フォントハッシュ作成中...',0
  1951. TableClrMes:    .dc.b    $0d,'          ',$0d,0
  1952.  
  1953. title1:        .dc.b    'GetMojiDriver V',0
  1954. title2:        .dc.b    ' Copyright 1996-98,2000 by AIG-Soft',$0d,$0a
  1955. *        .dc.b    '             Debug中 v001',$0d,$0a
  1956.         .dc.b    0
  1957. MesKeep:    .dc.b    '組み込みました',$0d,$0a,0
  1958. MesRelease:    .dc.b    '解除しました',$0d,$0a,0
  1959. ErrNoKumikomi:    .dc.b    '組み込まれていません'        * CrLfにつながる
  1960. CrLf        .dc.b    $0d,$0a,0
  1961. DeviceMes    .dc.b    'デバイス名:',0
  1962. *
  1963. ErrCantRdHash    .dc.b    'フォントハッシュファイルが読み込めません:',0
  1964. ErrCantWtHash    .dc.b    'フォントハッシュファイルが書き込めません:',0
  1965. ErrIllHash:    .dc.b    'フォントハッシュファイルではありません:',0
  1966. *ErrCantKpBuff2    .dc.b    'SetBlock不可で'
  1967. ErrCantKpBuff:    .dc.b    'フォントハッシュワークが確保できません',0
  1968. ErrAlreadySet:    .dc.b    'すでに組み込まれています',0
  1969. ErrDevUse    .dc.b    'はすでに使用されています',0
  1970. *
  1971. ErrCantDevice:    .dc.b    'DEVICE=で組み込まれています.',0
  1972. ErrCantJLock    .dc.b    '常駐ロックされています.',0
  1973. ErrCantResBuff:    .dc.b    'フォントハッシュワークが解放できません.'    * 次につながる
  1974. ErrCantRelease:    .dc.b    'GMDは解除できません',0
  1975. MesUsage:    .dc.b    'GMD [/h /g /o /r] [フォントハッシュファイル]',0
  1976. *
  1977. MesRevMode:    .dc.b    '反転文字読み取り:',0
  1978. MesRevOff:    .dc.b    '不'                * 次につながる
  1979. MesRevOn:    .dc.b    '可能',$0d,$0a,0
  1980. *
  1981. *********************************************************************
  1982. * オプション
  1983. *********************************************************************
  1984. * オプション名はコマンド名と同じにする
  1985.  
  1986.     .even
  1987.         * .dc.b work,フラグキャラクター
  1988.         * 1オプション分 1+1=2バイト
  1989. ComFlags:    * コマンドライン時有効フラグ
  1990. rflag        .dc.b    0,'R'    * 常駐解除フラグ
  1991. DevFlags:    * デバイスドライバ時にも有効フラグ
  1992. hflag        .dc.b    0,'H'    * 高位メモリー確保フラグ
  1993. gflag        .dc.b    0,'G'    * デバイス名を@GMDにする
  1994. oflag        .dc.b    0,'O'    * 反転文字を読むかどうか
  1995.         .dc.b    0,0    * end of table
  1996.  
  1997. *********************************************************************
  1998. * 非常駐ルーチンが使うワーク
  1999. *********************************************************************
  2000.     .bss
  2001.     .even
  2002. oldstack    .dc.l    0    * 元のスタックポイント
  2003. cline0        .dc.b    0    * 変換後コマンドラインサイズ
  2004. cline        .ds.b    256    * コマンドライン変換
  2005. HashName    .ds.b    96    * フォントハッシュファイル名
  2006.  
  2007.     .stack
  2008.     .even
  2009.     .ds.l    256        * スタック(コマンドライン起動時のみ使用)
  2010. initsp:
  2011.  
  2012. *********************************************************************
  2013.     .end    main
  2014.